/**
 @file ctc_linkagg_cli.c

 @author  Copyright (C) 2011 Centec Networks Inc.  All rights reserved.

 @date 2009-11-18

 @version v2.0

 This file contains linkagg cli function
*/

#include "ctc_debug.h"
#include "ctc_vlan_cli.h"
#include "ctc_cli.h"
#include "ctc_cli_common.h"
#include "ctc_error.h"
#include "ctc_api.h"
#include "ctcs_api.h"


#define CTC_CLI_LINKAGG_REPLACE_MEMBER_MAX  2048
#define CTC_CLI_LINKAGG_LSH_PORTS_MAX  8
CTC_CLI(ctc_cli_linkagg_create,
        ctc_cli_linkagg_create_cmd,
        "linkagg create linkagg AGG_ID (static {lmpf|mem-ascend-order|nonuc-detach|} |\
        failover(lmpf|)|\
        rr (random|)|\
        dynamic |)\
        {lsh-mode (next|next-local|all|all-local)|member-num NUM|session-preservation (spm-flow-num NUM|)|}",
        CTC_CLI_LINKAGG_M_STR,
        "Create linkagg group",
        CTC_CLI_LINKAGG_DESC,
        CTC_CLI_LINKAGG_ID_DESC,
        "Static linkagg group",
        "Local member first",
        "Member in ascend order",
        "Linkagg group only update nonuc ports",
        "Static linkagg group enable failover",
        "Local member first",
        "Round robin group",
        "Random rr",
        "Dynamic linkagg group",
        "Backup-port auto cfg mode",
        "Backup-port defaults to the next port in the linkagg member list",
        "Backup-port defaults to the next local port in the linkagg member list.if any",
        "Backup-port defaults to the next all other ports in this linkagg",
        "Backup-port defaults to the next all other local ports in this linkagg",
        "Member num",
        CTC_CLI_LINKAGG_MEM_NUM,
        "Session preservation",
        "SPM flow num",
        "Number")
{
    uint8 index = 0;
    int32 ret = CLI_SUCCESS;
    ctc_linkagg_group_t linkagg_grp;

    sal_memset(&linkagg_grp, 0, sizeof(ctc_linkagg_group_t));
    CTC_CLI_GET_UINT16("linkagg id", linkagg_grp.tid, argv[0]);

    linkagg_grp.linkagg_mode = CTC_LINKAGG_MODE_STATIC;
    linkagg_grp.member_num = 16;
    linkagg_grp.flow_num = 8192;

    index = CTC_CLI_GET_ARGC_INDEX("static");
    if(index != 0xFF)
    {
        linkagg_grp.linkagg_mode = CTC_LINKAGG_MODE_STATIC;
        linkagg_grp.member_num = 16;
    }

    index = CTC_CLI_GET_ARGC_INDEX("failover");
    if(index != 0xFF)
    {
        linkagg_grp.linkagg_mode = CTC_LINKAGG_MODE_STATIC_FAILOVER;
        linkagg_grp.member_num = 16;
    }

    index = CTC_CLI_GET_ARGC_INDEX("rr");
    if(index != 0xFF)
    {
        linkagg_grp.linkagg_mode = CTC_LINKAGG_MODE_RR;
        linkagg_grp.member_num = 16;
    }

    index = CTC_CLI_GET_ARGC_INDEX("dynamic");
    if(index != 0xFF)
    {
        linkagg_grp.linkagg_mode = CTC_LINKAGG_MODE_DLB;
        linkagg_grp.member_num = 32;
    }

    index = CTC_CLI_GET_ARGC_INDEX("random");
    if(index != 0xFF)
    {
        linkagg_grp.flag |= CTC_LINKAGG_GROUP_FLAG_RANDOM_RR;
    }

    index = CTC_CLI_GET_ARGC_INDEX("lmpf");
    if(index != 0xFF)
    {
        linkagg_grp.flag |= CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST;
    }

    index = CTC_CLI_GET_ARGC_INDEX("mem-ascend-order");
    if(index != 0xFF)
    {
        linkagg_grp.flag |= CTC_LINKAGG_GROUP_FLAG_MEM_ASCEND_ORDER;
    }

    index = CTC_CLI_GET_ARGC_INDEX("session-preservation");
    if(index != 0xFF)
    {
        linkagg_grp.flag |= CTC_LINKAGG_GROUP_FLAG_SPM_EN;
    }

    index = CTC_CLI_GET_ARGC_INDEX("nonuc-detach");
    if(index != 0xFF)
    {
        linkagg_grp.flag |= CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH;
    }

    index = CTC_CLI_GET_ARGC_INDEX("next");
    if (index != 0xFF)
    {
        linkagg_grp.lsh_mode = CTC_LINKAGG_LSH_MODE_NEXT;
    }
    index = CTC_CLI_GET_ARGC_INDEX("next-local");
    if (index != 0xFF)
    {
        linkagg_grp.lsh_mode = CTC_LINKAGG_LSH_MODE_NEXT_LOCAL;
    }
    index = CTC_CLI_GET_ARGC_INDEX("all");
    if (index != 0xFF)
    {
        linkagg_grp.lsh_mode = CTC_LINKAGG_LSH_MODE_ALL;
    }
    index = CTC_CLI_GET_ARGC_INDEX("all-local");
    if (index != 0xFF)
    {
        linkagg_grp.lsh_mode = CTC_LINKAGG_LSH_MODE_ALL_LOCAL;
    }

    index = CTC_CLI_GET_ARGC_INDEX("member-num");
    if(index != 0xFF)
    {
        CTC_CLI_GET_UINT16("group member num", linkagg_grp.member_num, argv[index+1]);
    }
    
    index = CTC_CLI_GET_ARGC_INDEX("spm-flow-num");
    if(index != 0xFF)
    {
        CTC_CLI_GET_UINT32("spm group flow num", linkagg_grp.flow_num, argv[index+1]);
    }
    
    if(g_ctcs_api_en)
    {
        ret = ctcs_linkagg_create(g_api_ldev, &linkagg_grp);
    }
    else
    {
        ret = ctc_linkagg_create(&linkagg_grp);
    }

    if (ret < 0)
    {
        ctc_cli_out("%% ret = %d, %s\n", ret, ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return ret;
}

CTC_CLI(ctc_cli_linkagg_remove,
        ctc_cli_linkagg_remove_cmd,
        "linkagg remove linkagg AGG_ID",
        CTC_CLI_LINKAGG_M_STR,
        "Remove linkagg group",
        CTC_CLI_LINKAGG_DESC,
        CTC_CLI_LINKAGG_ID_DESC)
{
    int32 ret = CLI_SUCCESS;
    uint16 tid = CTC_MAX_LINKAGG_GROUP_NUM;

    CTC_CLI_GET_UINT16("linkagg id", tid, argv[0]);

    if(g_ctcs_api_en)
    {
        ret = ctcs_linkagg_destroy(g_api_ldev, tid);
    }
    else
    {
        ret = ctc_linkagg_destroy(tid);
    }

    if (ret < 0)
    {
        ctc_cli_out("%% ret = %d, %s\n", ret, ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return ret;
}

CTC_CLI(ctc_cli_linkagg_add_or_remove_port,
        ctc_cli_linkagg_add_or_remove_port_cmd,
        "linkagg AGG_ID (add | remove) member-port GPHYPORT_ID",
        CTC_CLI_LINKAGG_M_STR,
        CTC_CLI_LINKAGG_ID_DESC,
        "Add member port to linkagg group",
        "Remove member port from linkagg group",
        "Member-port, global port",
        CTC_CLI_GPHYPORT_ID_DESC)
{
    int32 ret = CLI_SUCCESS;
    uint16 tid = CTC_MAX_LINKAGG_GROUP_NUM;
    uint32 gport = 0;

    CTC_CLI_GET_UINT16("linkagg id", tid, argv[0]);
    CTC_CLI_GET_UINT32("gport", gport, argv[2]);

    if (0 == sal_memcmp("ad", argv[1], 2))
    {
        if(g_ctcs_api_en)
        {
             ret = ctcs_linkagg_add_port(g_api_ldev, tid, gport);
        }
        else
        {
            ret = ctc_linkagg_add_port(tid, gport);
        }
    }
    else if (0 == sal_memcmp("re", argv[1], 2))
    {
        if(g_ctcs_api_en)
        {
             ret = ctcs_linkagg_remove_port(g_api_ldev, tid, gport);
        }
        else
        {
            ret = ctc_linkagg_remove_port(tid, gport);
        }
    }

    if (ret < 0)
    {
        ctc_cli_out("%% ret = %d, %s\n", ret, ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return ret;
}
#define g_tid       (CTC_VTY_CLIENT(vty)->linkagg_tid)
#define g_mem_num   (CTC_VTY_CLIENT(vty)->linkagg_mem_num)
#define g_mem_port  ((ctc_linkagg_port_t*)CTC_VTY_CLIENT(vty)->linkagg_mem_port)
CTC_CLI(ctc_cli_linkagg_add_or_remove_port_array,
        ctc_cli_linkagg_add_or_remove_port_array_cmd,
        "linkagg AGG_ID (add | remove) member-ports (gport GPHYPORT_ID {lmpf-en|nonuc-block-en|} |)  (end|) ",
        CTC_CLI_LINKAGG_M_STR,
        CTC_CLI_LINKAGG_ID_DESC,
        "Add member ports to linkagg group",
        "Remove member port from linkagg group",
        "Member-port, global port",
        "Gport",
        CTC_CLI_GPHYPORT_ID_DESC,
        "Local port priority first enable",
        "Nonuc block enable",
        "End")
{
    int32 ret = CLI_SUCCESS;
    uint8  is_end = 0;
    uint8  index = 0;
    uint16  cur_tid = CTC_MAX_LINKAGG_GROUP_NUM;

    if (!CTC_VTY_CLIENT(vty)->linkagg_mem_port)
    {
        CTC_VTY_CLIENT(vty)->linkagg_mem_port = mem_malloc(MEM_CLI_MODULE, sizeof(ctc_linkagg_port_t)*CTC_CLI_LINKAGG_REPLACE_MEMBER_MAX);
        if (!CTC_VTY_CLIENT(vty)->linkagg_mem_port) {
            ctc_cli_out("%% Alloc  memory  failed \n");
            return CLI_ERROR; 
        }
        sal_memset(CTC_VTY_CLIENT(vty)->linkagg_mem_port, 0, sizeof(ctc_linkagg_port_t)*CTC_CLI_LINKAGG_REPLACE_MEMBER_MAX);
    }
    CTC_CLI_GET_UINT16("linkagg id", cur_tid, argv[0]);

    if ((cur_tid != g_tid) && (g_tid != CTC_MAX_LINKAGG_GROUP_NUM))
    {
        sal_memset(g_mem_port, 0, sizeof(ctc_linkagg_port_t));
        g_mem_num = 0;
        g_tid = CTC_MAX_LINKAGG_GROUP_NUM;
        ret = CTC_E_INVALID_PARAM;
        ctc_cli_out("%% ret = %d, %s\n", ret, ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    g_tid = cur_tid;

    index = CTC_CLI_GET_ARGC_INDEX("gport");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT32("gport", g_mem_port[g_mem_num].gport, argv[index+1]);
        g_mem_num++;
    }
    index = CTC_CLI_GET_ARGC_INDEX("lmpf-en");
    if(index != 0xFF)
    {
        g_mem_port[g_mem_num -1].lmpf_en = 1;
    }

    index = CTC_CLI_GET_ARGC_INDEX("nonuc-block-en");
    if(index != 0xFF)
    {
        g_mem_port[g_mem_num -1].nonuc_block_en = 1;
    }

    index = CTC_CLI_GET_ARGC_INDEX("end");
    if (0xFF != index)
    {
        is_end = 1;
    }

    if (is_end)
    {
        if (0 == sal_memcmp("ad", argv[1], 2))
        {
            if(g_ctcs_api_en)
            {
                 ret = ctcs_linkagg_add_ports(g_api_ldev, g_tid, g_mem_num, g_mem_port);
            }
            else
            {
                ret = ctc_linkagg_add_ports( g_tid, g_mem_num, g_mem_port);
            }
        }
        else if (0 == sal_memcmp("re", argv[1], 2))
        {
            if(g_ctcs_api_en)
            {
                 ret = ctcs_linkagg_remove_ports(g_api_ldev, g_tid,  g_mem_num, g_mem_port);
            }
            else
            {
                ret = ctc_linkagg_remove_ports( g_tid,  g_mem_num, g_mem_port);
            }
        }

        sal_memset(g_mem_port, 0, sizeof(ctc_linkagg_port_t)*CTC_CLI_LINKAGG_REPLACE_MEMBER_MAX);
        g_mem_num = 0;
        g_tid = CTC_MAX_LINKAGG_GROUP_NUM;
        if (ret < 0)
        {
            ctc_cli_out("%% ret = %d, %s\n", ret, ctc_get_error_desc(ret));
            return CLI_ERROR;
        }
    }
    else
    {
        if (g_mem_num > CTC_CLI_LINKAGG_REPLACE_MEMBER_MAX)
        {
            sal_memset(g_mem_port, 0, sizeof(ctc_linkagg_port_t));
            g_mem_num = 0;
            g_tid = CTC_MAX_LINKAGG_GROUP_NUM;
            ret = CTC_E_INVALID_PARAM;
            ctc_cli_out("%% ret = %d, %s\n", ret, ctc_get_error_desc(ret));
            return CLI_ERROR;
        }
    }

  
    return ret;
}


CTC_CLI(ctc_cli_linkagg_show_member_port,
        ctc_cli_linkagg_show_member_port_cmd,
        "show linkagg AGG_ID member-ports",
        CTC_CLI_SHOW_STR,
        CTC_CLI_LINKAGG_M_STR,
        CTC_CLI_LINKAGG_ID_DESC,
        "Member ports of linkagg group")
{
    int32 ret = CLI_SUCCESS;
    uint16 cnt  = 0;
    uint16 idx = 0;
    uint16 tid = CTC_MAX_LINKAGG_GROUP_NUM;
    uint32* p_gports;
    uint16 max_num = 0;

    CTC_CLI_GET_UINT16("linkagg id", tid, argv[0]);

    if (g_ctcs_api_en)
    {
        ret = ctcs_linkagg_get_max_mem_num(g_api_ldev, &max_num);
    }
    else
    {
        ret =  ctc_linkagg_get_max_mem_num(&max_num);
    }

    if (ret < 0)
    {
        ctc_cli_out("%% ret = %d, %s\n", ret, ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    p_gports = (uint32*)mem_malloc(MEM_CLI_MODULE, sizeof(uint32) * max_num *2); /*size couple for mode56, if not may lead to the core dumped*/
    if (NULL == p_gports)
    {
        ctc_cli_out("%% Alloc  memory  failed \n");
        return CLI_ERROR; 
    }

    sal_memset(p_gports, 0, sizeof(uint32) * max_num *2);

    if(g_ctcs_api_en)
    {
        ret = ctcs_linkagg_get_member_ports(g_api_ldev, tid, p_gports, &cnt);
    }
    else
    {
        ret = ctc_linkagg_get_member_ports(tid, p_gports, &cnt);
    }

    if (ret < 0)
    {
        ctc_cli_out("%% ret = %d, %s\n", ret, ctc_get_error_desc(ret));
        mem_free(p_gports);
        return CLI_ERROR;
    }

    ctc_cli_out("%-11s%s\n", "No.", "Member-Gport");
    ctc_cli_out("----------------------\n");

    for (idx = 0; idx < cnt; idx++)
    {
        ctc_cli_out("%-11u0x%04X\n", idx + 1, p_gports[idx]);
    }

    mem_free(p_gports);
    p_gports = NULL;

    return ret;
}

CTC_CLI(ctc_cli_linkagg_debug_on,
        ctc_cli_linkagg_debug_on_cmd,
        "debug linkagg (ctc|sys) (debug-level {func|param|info|error} |)",
        CTC_CLI_DEBUG_STR,
        CTC_CLI_LINKAGG_M_STR,
        "CTC Layer",
        "SYS Layer",
        CTC_CLI_DEBUG_LEVEL_STR,
        CTC_CLI_DEBUG_LEVEL_FUNC,
        CTC_CLI_DEBUG_LEVEL_PARAM,
        CTC_CLI_DEBUG_LEVEL_INFO,
        CTC_CLI_DEBUG_LEVEL_ERROR)
{
    uint32 typeenum = 0;
    uint8 level = CTC_DEBUG_LEVEL_INFO;
    uint8 index = 0;

    if (0 == sal_memcmp(argv[0], "ctc", 3))
    {
        typeenum = LINKAGG_CTC;
    }
    else
    {
        typeenum = LINKAGG_SYS;
    }

    index = CTC_CLI_GET_ARGC_INDEX("debug-level");
    if (index != 0xFF)
    {
        level = CTC_DEBUG_LEVEL_NONE;
        index = CTC_CLI_GET_ARGC_INDEX("func");
        if (index != 0xFF)
        {
            level |= CTC_DEBUG_LEVEL_FUNC;
        }

        index = CTC_CLI_GET_ARGC_INDEX("param");
        if (index != 0xFF)
        {
            level |= CTC_DEBUG_LEVEL_PARAM;
        }

        index = CTC_CLI_GET_ARGC_INDEX("info");
        if (index != 0xFF)
        {
            level |= CTC_DEBUG_LEVEL_INFO;
        }

        index = CTC_CLI_GET_ARGC_INDEX("error");
        if (index != 0xFF)
        {
            level |= CTC_DEBUG_LEVEL_ERROR;
        }
    }

    ctc_debug_set_flag("linkagg", "linkagg", typeenum, level, TRUE);

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_linkagg_debug_off,
        ctc_cli_linkagg_debug_off_cmd,
        "no debug linkagg (ctc|sys)",
        CTC_CLI_NO_STR,
        CTC_CLI_DEBUG_STR,
        CTC_CLI_LINKAGG_M_STR,
        "CTC Layer",
        "SYS Layer")
{
    uint32 typeenum = 0;
    uint8 level = 0;

    if (0 == sal_memcmp(argv[0], "ctc", 3))
    {
        typeenum = LINKAGG_CTC;
    }
    else
    {
        typeenum = LINKAGG_SYS;
    }

    ctc_debug_set_flag("linkagg", "linkagg", typeenum, level, FALSE);

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_linkagg_show_local_member_port,
        ctc_cli_linkagg_show_local_member_port_cmd,
        "show linkagg AGG_ID local-port",
        CTC_CLI_SHOW_STR,
        CTC_CLI_LINKAGG_M_STR,
        CTC_CLI_LINKAGG_ID_DESC,
        "One local port of the linkagg member ports"
        )
{
    int32 ret = CLI_SUCCESS;
    uint16 cnt  = 0;
    uint16 tid = 0;
    uint32 gport = 0;
    CTC_CLI_GET_UINT16("linkagg id", tid, argv[0]);

    if(g_ctcs_api_en)
    {
       ret = ctcs_linkagg_get_1st_local_port(g_api_ldev, tid, &gport, &cnt);
    }
    else
    {
        ret = ctc_linkagg_get_1st_local_port(g_api_ldev, tid, &gport, &cnt);
    }
    if (ret < 0)
    {
        ctc_cli_out("%% ret = %d, %s\n", ret, ctc_get_error_desc(ret));
        return ret;
    }

    if (cnt > 0)
    {
        ctc_cli_out("Member cnt: %-8d One of the members is: 0x%04x\n", cnt, gport);
    }
    else
    {
        ctc_cli_out("Member cnt: %-8d\n", cnt);
    }

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_linkagg_replace_ports,
        ctc_cli_linkagg_replace_ports_cmd,
        "linkagg AGG_ID replace member-port [ARRAY] ",
        CTC_CLI_LINKAGG_M_STR,
        CTC_CLI_LINKAGG_ID_DESC,
        "Replace member ports for linkagg group",
        "Array of gport list",
        "Elements of array, input as [xxx,xxx,xxx]")
{
    int32 ret = CLI_SUCCESS;
    uint16 tid = CTC_MAX_LINKAGG_GROUP_NUM;
    uint32 mem_num = CTC_CLI_LINKAGG_REPLACE_MEMBER_MAX;
    uint32* linkagg_mem_port = NULL;

    CTC_CLI_GET_UINT16("linkagg id", tid, argv[0]);
    linkagg_mem_port = (uint32*)mem_malloc(MEM_CLI_MODULE, sizeof(uint32) * CTC_CLI_LINKAGG_REPLACE_MEMBER_MAX);
    if (NULL == linkagg_mem_port)
    {
        ctc_cli_out("%% Alloc  memory  failed \n");
        return CLI_ERROR; 
    }
    sal_memset(linkagg_mem_port, 0, sizeof(uint32) * CTC_CLI_LINKAGG_REPLACE_MEMBER_MAX);

    CTC_CLI_GET_UINT32_ARRAY("gport id", linkagg_mem_port, &mem_num, argv[1], ret);
    if (ret < 0)
    {
        mem_free(linkagg_mem_port);
        ctc_cli_out("%% %s \n\r", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    if (g_ctcs_api_en)
    {
        ret = ctcs_linkagg_replace_ports(g_api_ldev, tid, linkagg_mem_port, mem_num);
    }
    else
    {
        ret = ctc_linkagg_replace_ports(tid, linkagg_mem_port, mem_num);
    }
    mem_free(linkagg_mem_port);
    if (ret < 0)
    {
        ctc_cli_out("%% ret = %d, %s\n", ret, ctc_get_error_desc(ret));
        return CLI_ERROR;
    }


    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_linkagg_set_lsh,
        ctc_cli_linkagg_set_lsh_cmd,
        "linkagg AGG_ID member-port GPORT ({backup-port [ARRAY]} | lsh-mode (next|next-local|all|all-local))",
        CTC_CLI_LINKAGG_M_STR,
        CTC_CLI_LINKAGG_ID_DESC,
        "Member-port, global port",
        CTC_CLI_GPHYPORT_ID_DESC,
        "Backup-port, global port",
        "Elements of array, input as [xxx,xxx,xxx]",
        "Backup-port auto cfg mode",
        "Backup-port defaults to the next port in the linkagg member list",
        "Backup-port defaults to the next local port in the linkagg member list.if any",
        "Backup-port defaults to the next all other ports in this linkagg",
        "Backup-port defaults to the next all other local ports in this linkagg")
{
    int32 ret = CLI_SUCCESS;
    uint16 tid = CTC_MAX_LINKAGG_GROUP_NUM;
    uint32 mem_port = MAX_PORT_NUM_PER_CHIP;
    uint32 bak_num = CTC_CLI_LINKAGG_LSH_PORTS_MAX;
    ctc_linkagg_lsh_t port_array;
    uint8 index = 0;
    uint8 mode = 0;

    CTC_CLI_GET_UINT16("linkagg id", tid, argv[0]);
    CTC_CLI_GET_UINT32("gport", mem_port, argv[1]);
    index = CTC_CLI_GET_ARGC_INDEX("backup-port");
    if (0xFF != index)
    {
        port_array.backup_ports = (uint32 *)mem_malloc(MEM_CLI_MODULE, sizeof(uint32) * CTC_CLI_LINKAGG_LSH_PORTS_MAX);
        if (NULL == port_array.backup_ports)
        {
            ctc_cli_out("%% Alloc  memory  failed \n");
            return CLI_ERROR; 
        }
        sal_memset(port_array.backup_ports, 0, sizeof(uint32) * CTC_CLI_LINKAGG_LSH_PORTS_MAX);
        CTC_CLI_GET_UINT32_ARRAY("gport id", port_array.backup_ports, &bak_num, argv[index+1], ret);
        if (ret < 0)
        {
            mem_free(port_array.backup_ports);
            ctc_cli_out("%% %s \n\r", ctc_get_error_desc(ret));
            return CLI_ERROR;
        }
    }

    index = CTC_CLI_GET_ARGC_INDEX("lsh-mode");
    if (0xFF != index)
    {
        index = CTC_CLI_GET_ARGC_INDEX("next");
        if (0xFF != index)
        {
            mode = CTC_LINKAGG_LSH_MODE_NEXT;
        }

        index = CTC_CLI_GET_ARGC_INDEX("next-local");
        if (0xFF != index)
        {
            mode = CTC_LINKAGG_LSH_MODE_NEXT_LOCAL;
        }

        index = CTC_CLI_GET_ARGC_INDEX("all");
        if (0xFF != index)
        {
            mode = CTC_LINKAGG_LSH_MODE_ALL;
        }

        index = CTC_CLI_GET_ARGC_INDEX("all-local");
        if (0xFF != index)
        {
            mode = CTC_LINKAGG_LSH_MODE_ALL_LOCAL;
        }
    }

    if(mode)
    {
        port_array.lsh_mode = mode;
        if (g_ctcs_api_en)
        {
            ret = ctcs_linkagg_set_lsh(g_api_ldev, tid, mem_port, &port_array);
        }
        else
        {
            ret = ctc_linkagg_set_lsh(tid, mem_port, &port_array);
        }
	    if (ret < 0)
        {
            ctc_cli_out("%% ret = %d, %s\n", ret, ctc_get_error_desc(ret));
            return CLI_ERROR;
        }
    }
    else
    {
        port_array.lsh_mode = CTC_LINKAGG_LSH_MODE_USERDEF;
        port_array.count = bak_num;

        if (g_ctcs_api_en)
        {
            ret = ctcs_linkagg_set_lsh(g_api_ldev, tid, mem_port, &port_array);
        }
        else
        {
            ret = ctc_linkagg_set_lsh(tid, mem_port, &port_array);
        }

        mem_free(port_array.backup_ports);
        port_array.backup_ports = NULL;
        if (ret < 0)
        {
            ctc_cli_out("%% ret = %d, %s\n", ret, ctc_get_error_desc(ret));
            return CLI_ERROR;
        }

    }

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_linkagg_get_lsh,
        ctc_cli_linkagg_get_lsh_cmd,
        "show linkagg AGG_ID member-ports GPORT backup-ports",
        CTC_CLI_SHOW_STR,
        CTC_CLI_LINKAGG_M_STR,
        CTC_CLI_LINKAGG_ID_DESC,
        "Member-port, global port",
        CTC_CLI_GPHYPORT_ID_DESC,
        "Backup ports of member port")
{
    int32 ret = CLI_SUCCESS;
    uint16 idx = 0;
    uint16 tid = CTC_MAX_LINKAGG_GROUP_NUM;
    uint32 mem_port  = MAX_PORT_NUM_PER_CHIP;
    ctc_linkagg_lsh_t port_array;

    CTC_CLI_GET_UINT16("linkagg id", tid, argv[0]);
    CTC_CLI_GET_UINT32("gport", mem_port, argv[1]);

    port_array.count = CTC_CLI_LINKAGG_LSH_PORTS_MAX;
    port_array.backup_ports = (uint32*)mem_malloc(MEM_CLI_MODULE, sizeof(uint32) * CTC_CLI_LINKAGG_LSH_PORTS_MAX);
    if (NULL == port_array.backup_ports)
    {
        ctc_cli_out("%% Alloc  memory  failed \n");
        return CLI_ERROR; 
    }

    sal_memset(port_array.backup_ports, 0, sizeof(uint32) * CTC_CLI_LINKAGG_LSH_PORTS_MAX);

    if (g_ctcs_api_en)
    {
        ret = ctcs_linkagg_get_lsh(g_api_ldev, tid, mem_port, &port_array);
    }
    else
    {
        ret =  ctc_linkagg_get_lsh(tid, mem_port, &port_array);
    }

    if (ret < 0)
    {
        ctc_cli_out("%% ret = %d, %s\n", ret, ctc_get_error_desc(ret));
        mem_free(port_array.backup_ports);
        return CLI_ERROR;
    }

    ctc_cli_out("%-11s%s\n", "No.", "Member-Gport");
    ctc_cli_out("----------------------\n");

    for (idx = 0; idx < port_array.count; idx++)
    {
        ctc_cli_out("%-11u0x%04X\n", idx + 1, port_array.backup_ports[idx]);
    }

    mem_free(port_array.backup_ports);
    port_array.backup_ports = NULL;

    return ret;
}


CTC_CLI(ctc_cli_linkagg_set_nonuc_ports,
        ctc_cli_linkagg_set_nonuc_ports_cmd,
        "linkagg AGG_ID nonuc-ports gport-array [ARRAY] ",
        CTC_CLI_LINKAGG_M_STR,
        CTC_CLI_LINKAGG_ID_DESC,
        "Add nonuc ports to linkagg group",
        "Array of gport list",
        "Elements of array, input as [xxx,xxx,xxx]")
{
    int32 ret = CLI_SUCCESS;
    uint16 nonuc_tid = CTC_MAX_LINKAGG_GROUP_NUM;
    uint32* linkagg_nonuc_port = NULL;
    uint32 max_member_num = CTC_CLI_LINKAGG_REPLACE_MEMBER_MAX;

    CTC_CLI_GET_UINT16("linkagg id", nonuc_tid, argv[0]);

    linkagg_nonuc_port = (uint32*)mem_malloc(MEM_CLI_MODULE, sizeof(uint32) * CTC_CLI_LINKAGG_REPLACE_MEMBER_MAX);
    if (NULL == linkagg_nonuc_port)
    {
        ctc_cli_out("%% Alloc  memory  failed \n");
        return CLI_ERROR; 
    }
    sal_memset(linkagg_nonuc_port, 0, sizeof(uint32) * CTC_CLI_LINKAGG_REPLACE_MEMBER_MAX);
   CTC_CLI_GET_UINT32_ARRAY("gport id", linkagg_nonuc_port, &max_member_num, argv[1], ret);
   if (ret < 0)
   {
       mem_free(linkagg_nonuc_port);
       ctc_cli_out("%% %s \n\r", ctc_get_error_desc(ret));
       return CLI_ERROR;
   }
   
   if(g_ctcs_api_en)
   {
       ret = ctcs_linkagg_set_nonuc_ports(g_api_ldev, nonuc_tid, linkagg_nonuc_port, max_member_num);
   }
   else
   {
       ret = ctc_linkagg_set_nonuc_ports(nonuc_tid, linkagg_nonuc_port, max_member_num);
   }

   mem_free(linkagg_nonuc_port);
   if (ret < 0)
   {
       ctc_cli_out("%% ret = %d, %s\n", ret, ctc_get_error_desc(ret));
       return CLI_ERROR;
   }

    return ret;
}


CTC_CLI(ctc_cli_linkagg_get_nonuc_ports,
        ctc_cli_linkagg_get_nonuc_ports_cmd,
        "show linkagg AGG_ID nonuc-ports",
        CTC_CLI_SHOW_STR,
        CTC_CLI_LINKAGG_M_STR,
        CTC_CLI_LINKAGG_ID_DESC,
        "Nonuc member ports of linkagg group")
{
    int32 ret = CLI_SUCCESS;
    uint16 cnt  = 0;
    uint16 idx = 0;
    uint16 tid = CTC_MAX_LINKAGG_GROUP_NUM;
    uint32* p_gports;
    uint16 max_num = 0;

    CTC_CLI_GET_UINT16("linkagg id", tid, argv[0]);

    if (g_ctcs_api_en)
    {
        ret = ctcs_linkagg_get_max_mem_num(g_api_ldev, &max_num);
    }
    else
    {
        ret =  ctc_linkagg_get_max_mem_num(&max_num);
    }
    if (ret < 0)
    {
        ctc_cli_out("%% ret = %d, %s\n", ret, ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    p_gports = (uint32*)mem_malloc(MEM_CLI_MODULE, sizeof(uint32) * max_num *2); /*size couple for mode56, if not may lead to the core dumped*/
    if (NULL == p_gports)
    {
        ctc_cli_out("%% Alloc  memory  failed \n");
        return CLI_ERROR; 
    }

    sal_memset(p_gports, 0, sizeof(uint32) * max_num *2);
    if(g_ctcs_api_en)
    {
        ret = ctcs_linkagg_get_nonuc_ports(g_api_ldev, tid, p_gports, &cnt);
    }
    else
    {
        ret = ctc_linkagg_get_nonuc_ports(tid, p_gports, &cnt);
    }
    if (ret < 0)
    {
        ctc_cli_out("%% ret = %d, %s\n", ret, ctc_get_error_desc(ret));
        mem_free(p_gports);
        return CLI_ERROR;
    }

    ctc_cli_out("%-11s%s\n", "No.", "Nonuc-member-Gport");
    ctc_cli_out("----------------------\n");

    for (idx = 0; idx < cnt; idx++)
    {
        ctc_cli_out("%-11u0x%04X\n", idx + 1, p_gports[idx]);
    }

    mem_free(p_gports);
    p_gports = NULL;

    return ret;
}


int32
ctc_linkagg_cli_init(void)
{
    install_element(CTC_SDK_MODE, &ctc_cli_linkagg_create_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_linkagg_remove_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_linkagg_add_or_remove_port_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_linkagg_add_or_remove_port_array_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_linkagg_show_member_port_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_linkagg_show_local_member_port_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_linkagg_replace_ports_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_linkagg_set_lsh_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_linkagg_get_lsh_cmd);

    install_element(CTC_SDK_MODE, &ctc_cli_linkagg_debug_on_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_linkagg_debug_off_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_linkagg_set_nonuc_ports_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_linkagg_get_nonuc_ports_cmd);

    return CLI_SUCCESS;
}

